<?php

App::uses('TestEnvironment', 'Lib');
App::uses('FileSystem', 'Base.Lib');
App::uses('ConfigurationKeys', 'ConfigurationKeys.Lib');
App::uses('PsfmAdmin', 'Lib');

class SourceDocumentTest extends CakeTestCase {

    public $fixtures = array(
        'plugin.ConfigurationKeys.SettedConfigurationKey',
        'plugin.ConfigurationKeys.ConfigurationKey',
        'RawFile',
        'RawFileTag',
        'SourceDocument',
        'SourceDocumentTag',
        'Tag',
    );

    /**
     * @var SourceDocument
     */
    private $SourceDocument;

    /**
     * @var RawFile
     */
    private $RawFile;

    /**
     * @var SourceDocumentTag
     */
    private $SourceDocumentTag;

    /**
     *
     * @var RawFileTag
     */
    private $RawFileTag;

    public function setUp() {
        PsfmAdmin::customDataModelsClearCache();
        $this->SourceDocument = ClassRegistry::init('SourceDocument');
        $this->RawFile = ClassRegistry::init('RawFile');
        $this->Tag = ClassRegistry::init('Tag');
        $this->RawFileTag = ClassRegistry::init('RawFileTag');
        $this->SourceDocumentTag = ClassRegistry::init('SourceDocumentTag');

        ConfigurationKeys::setKeyValue(
                'raw_files_directory'
                , FileSystem::createTemporaryDirectory()
        );

        ConfigurationKeys::setKeyValue(
                'shared_files_directory'
                , FileSystem::createTemporaryDirectory()
        );

        ConfigurationKeys::setKeyValue(
                'joined_document_regex'
                , '/^([\S]+)/'
        );
    }

    public function tearDown() {
        FileSystem::recursiveRemoveDirectory(
                ConfigurationKeys::getKeyValue('raw_files_directory')
        );
        FileSystem::recursiveRemoveDirectory(
                ConfigurationKeys::getKeyValue('shared_files_directory')
        );
        parent::tearDown();
    }

    public function testTablesEngine() {
        $models = array($this->SourceDocument, $this->RawFile, $this->Tag, $this->RawFileTag, $this->SourceDocumentTag);
        foreach ($models as $model) {
            $tableName = $model->tablePrefix . $model->table;
            $r = $model->query("SHOW TABLE STATUS WHERE Name = '$tableName'");            
            $this->assertEqual($r[0]['TABLES']['Engine'], 'InnoDB');            
        }
    }

    public function testRename() {
        //Check no rows saved
        $this->assertEqual($this->RawFile->find('count'), 0);
        $this->assertEqual($this->SourceDocument->find('count'), 0);
        $this->assertEqual($this->RawFileTag->find('count'), 0);


        //Create raw file
        $this->assertEqual(file_exists(ConfigurationKeys::getKeyValue('raw_files_directory') . DS . 'document file 1'), false);
        $this->RawFile->create();
        $result = $this->RawFile->save(array(
            $this->RawFile->alias => array(
                'name' => 'document file 1'
            )
        ));
        $this->assertEqual($this->RawFile->validationErrors, array());
        $this->assertNotEqual($result, false);
        $this->assertEqual(file_exists(ConfigurationKeys::getKeyValue('raw_files_directory') . DS . 'document file 1'), true);
        $this->assertEqual($this->RawFile->find('count'), 1);
        $this->assertEqual($this->SourceDocument->find('count'), 1);
        $this->assertEqual($this->RawFileTag->find('count'), 0);
        $rawFile = $this->RawFile->find('first');

        //Create raw file tag
        $this->Tag->create();
        $this->Tag->save(array(
            'Tag' => array(
                'name' => 'Tag test'
            )
        ));
        $tag = $this->Tag->read();
        $this->assertEqual(empty($tag), false);

        $rawFileTag['RawFileTag'] = array(
            'raw_file_id' => $rawFile['RawFile']['id'],
            'tag_id' => $tag['Tag']['id'],
            'name' => $rawFile['RawFile']['name']
        );
        $this->RawFileTag->create();
        $this->RawFileTag->save($rawFileTag);
        $rawFileTag = $this->RawFileTag->read();
        $this->assertEqual(empty($rawFileTag), false);

        $this->assertEqual($this->RawFile->find('count'), 1);
        $this->assertEqual($this->SourceDocument->find('count'), 1);
        $this->assertEqual($this->RawFileTag->find('count'), 1);

        //Rename source document
        $this->assertEqual($rawFile['RawFile']['name'], 'document file 1');
        $sourceDocument = $this->SourceDocument->find('first');
        $this->assertEqual($sourceDocument['SourceDocument']['name'], 'document');
        $sourceDocument['SourceDocument']['name'] = 'changed';
        $result = $this->SourceDocument->save($sourceDocument);
        $this->assertEqual($this->SourceDocument->validationErrors, array());
        $this->assertNotEqual($result, false);

        $this->assertEqual($this->RawFile->find('count'), 1);
        $this->assertEqual($this->SourceDocument->find('count'), 1);
        $this->assertEqual($this->RawFileTag->find('count'), 1);

        $sourceDocument = $this->SourceDocument->find('first');
        $this->assertEqual($sourceDocument['SourceDocument']['name'], 'changed');
        $rawFile = $this->RawFile->find('first');
        $this->assertEqual($rawFile['RawFile']['name'], 'changed file 1');
        $rawFileTag = $this->RawFileTag->find('first');
        $this->assertEqual($rawFileTag['RawFileTag']['name'], 'changed file 1');
    }

    public function testNoActionOnFail() {
        //Check no rows saved
        $this->assertEqual($this->RawFile->find('count'), 0);
        $this->assertEqual($this->SourceDocument->find('count'), 0);
        $this->assertEqual($this->RawFileTag->find('count'), 0);

        //Create raw file 1
        $this->assertEqual(file_exists(ConfigurationKeys::getKeyValue('raw_files_directory') . DS . 'document file 1'), false);
        $this->RawFile->create();
        $result = $this->RawFile->save(array(
            $this->RawFile->alias => array(
                'name' => 'document file 1'
            )
        ));
        $this->assertEqual($this->RawFile->validationErrors, array());
        $this->assertNotEqual($result, false);
        $this->assertEqual(file_exists(ConfigurationKeys::getKeyValue('raw_files_directory') . DS . 'document file 1'), true);
        $rawFile = $this->RawFile->read();

        // Create tag
        $this->Tag->create();
        $this->Tag->save(array(
            'Tag' => array(
                'name' => 'Tag name'
            )
        ));
        $tag = $this->Tag->read();
        $this->assertEqual(empty($tag), false);



        // Create source document tag
        $sourceDocument = $this->SourceDocument->find('first');
        $this->SourceDocumentTag->create();
        $this->SourceDocumentTag->save(array(
            'SourceDocumentTag' => array(
                'tag_id' => $tag['Tag']['id'],
                'source_document_id' => $sourceDocument['SourceDocument']['id'],
            )
        ));
        $sourceDocumentTag = $this->SourceDocumentTag->read();
        $this->assertEqual(empty($sourceDocumentTag), false);
        $rawFileTag = $this->RawFileTag->find('first');
        $this->assertEqual(empty($rawFileTag), false);

        $this->assertEqual($this->RawFile->find('count'), 1);
        $this->assertEqual($this->SourceDocument->find('count'), 1);
        $this->assertEqual($this->Tag->find('count'), 1);
        $this->assertEqual($this->SourceDocumentTag->find('count'), 1);
        $this->assertEqual($this->RawFileTag->find('count'), 1);

        $changedRawFile = $rawFile;
        $changedRawFile['RawFile']['name'] = 'changed file 1';
        $changedRawFileTag = $rawFileTag;
        $changedRawFileTag['RawFileTag']['name'] = 'changed file 1';

        $this->assertEqual(file_exists($this->RawFile->getAbsolutePath($rawFile)), true);
        $this->assertEqual(file_exists($this->RawFile->getAbsolutePath($changedRawFile)), false);
        $this->assertEqual(file_exists($this->RawFileTag->absolutePath($rawFileTag)), true);
        $this->assertEqual(file_exists($this->RawFileTag->absolutePath($changedRawFileTag)), false);

        // Block raw_files_directory and try rename
        $this->assertEqual(empty($sourceDocument), false);
        $sourceDocument['SourceDocument']['name'] = 'changed';

        chmod(ConfigurationKeys::getKeyValue('raw_files_directory'), 0);
        $this->assertEqual(is_writeable($this->RawFile->getAbsolutePath($rawFile)), false);
        try {
            $this->SourceDocument->save($sourceDocument);
            $result = true;
        } catch (Exception $ex) {
            $result = false;
        }
        $this->assertEqual($result, false);

        $rawFile = $this->RawFile->find('first');
        $this->assertEqual($rawFile['RawFile']['name'], 'document file 1');
        $rawFileTag = $this->RawFileTag->find('first');
        $this->assertEqual($rawFileTag['RawFileTag']['name'], 'document file 1');
        chmod(ConfigurationKeys::getKeyValue('raw_files_directory'), 0777);
        $this->assertEqual(file_exists($this->RawFile->getAbsolutePath($rawFile)), true);
        $this->assertEqual(file_exists($this->RawFile->getAbsolutePath($changedRawFile)), false);
        $this->assertEqual(file_exists($this->RawFileTag->absolutePath($rawFileTag)), true);
        $this->assertEqual(file_exists($this->RawFileTag->absolutePath($changedRawFileTag)), false);

        // Block shared_files_directory and try rename
        $this->assertEqual(empty($sourceDocument), false);
        $sourceDocument['SourceDocument']['name'] = 'changed';

        chmod(ConfigurationKeys::getKeyValue('shared_files_directory'), 0);
        try {
            $this->SourceDocument->save($sourceDocument);
            $result = true;
        } catch (Exception $ex) {
            $result = false;
        }
        $this->assertEqual($result, false);

        chmod(ConfigurationKeys::getKeyValue('shared_files_directory'), 0777);
        $rawFile = $this->RawFile->find('first');
        $this->assertEqual($rawFile['RawFile']['name'], 'document file 1');
        $rawFileTag = $this->RawFileTag->find('first');
        $this->assertEqual($rawFileTag['RawFileTag']['name'], 'document file 1');
        $this->assertEqual(file_exists($this->RawFile->getAbsolutePath($rawFile)), true);
        $this->assertEqual(file_exists($this->RawFile->getAbsolutePath($changedRawFile)), false);
        $this->assertEqual(file_exists($this->RawFileTag->absolutePath($rawFileTag)), true);
        $this->assertEqual(file_exists($this->RawFileTag->absolutePath($changedRawFileTag)), false);

        // Unblock shared and raw files_directory and try rename
        $this->assertEqual(empty($sourceDocument), false);
        $sourceDocument['SourceDocument']['name'] = 'changed';
        $this->assertNotEqual($this->SourceDocument->save($sourceDocument), false);


        $this->assertEqual(file_exists($this->RawFile->getAbsolutePath($rawFile)), false);
        $this->assertEqual(file_exists($this->RawFile->getAbsolutePath($changedRawFile)), true);
        $this->assertEqual(file_exists($this->RawFileTag->absolutePath($rawFileTag)), false);
        $this->assertEqual(file_exists($this->RawFileTag->absolutePath($changedRawFileTag)), true);
    }

    private function _showDirs() {
        system("tree " . ConfigurationKeys::getKeyValue('raw_files_directory') . ' ' . ConfigurationKeys::getKeyValue('shared_files_directory'));
    }

}